package com.ling.common.library.net

import android.content.Context
import android.net.wifi.WifiManager
import android.util.Log
import fi.iki.elonen.NanoHTTPD
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.BufferedInputStream

/**
 * @author Ling
 * @date :2025/2/17 16:55
 */
class StreamVideoProxyServer private constructor(port: Int) : NanoHTTPD(port) {

    companion object{
        private const val PORT = 42955
        private var singleInstance  : StreamVideoProxyServer? = null


        @Synchronized
        fun getSingInstance() : StreamVideoProxyServer {
            if(singleInstance == null){
                singleInstance = StreamVideoProxyServer(PORT)
            }
            return singleInstance!!
        }

        fun destroyServer(){
            singleInstance?.destroy()
            singleInstance = null
        }
    }


    private var currentStreamUrl : String? = null
    private var okHttpClient : OkHttpClient? = null

    private fun destroy(){
        stop()
        try {
            okHttpClient?.dispatcher?.executorService?.shutdownNow()
        } catch (_: Exception) {
        }
    }

    private fun getOkHttpClient() : OkHttpClient{
        if(okHttpClient == null){
            okHttpClient = OkHttpUtil.getOkHttpClint()
        }
        return okHttpClient!!
    }


    fun setProxyUrl(url: String) {
        showLog("setProxyUrl:$url")
        try {
            currentStreamUrl = url
            if (!isAlive) {
                start()
            }
        } catch (e: Exception) {
            showLog("setProxyUrl:$e")
        }
    }

    //返回中转视频地址，调用前先setProxyUrl()
    fun getProxyVideoUrl(context: Context): String {
        return "http://" + getLocalIpStr(context) + ":" + PORT + "/proxyVideo?time=" + System.currentTimeMillis()
    }

    fun getLocalIpStr(context: Context): String {
        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE)
        if (wifiManager != null && wifiManager is WifiManager) {
            val wifiInfo = wifiManager.connectionInfo?.ipAddress ?: return ""
            return (((wifiInfo and 0xff).toString() + "." + ((wifiInfo shr 8) and 0xff)) + "." + ((wifiInfo shr 16) and 0xff)) + "." + ((wifiInfo shr 24) and 0xff)
        }
        return ""
    }


    private fun getProxyVideoStream(session: IHTTPSession) : Response?{
        val rangeHeader = session.headers["range"]

        val requestBuilder = Request.Builder().url(currentStreamUrl ?: "").header("Connection", "close")
        val request = if(session.method == Method.HEAD){
            requestBuilder.head().build()
        }else{
            requestBuilder.get().build()
        }

        val connectResponse = try {
            getOkHttpClient().newCall(request).execute()
        } catch (_: Exception) {
            Log.e("--->", "getProxyVideoStream: request error")
            null
        }
        if(connectResponse == null || !connectResponse.isSuccessful) return null

        if(session.method == Method.HEAD){
            val length = connectResponse.header("Content-Length" , "0")
            val response = newFixedLengthResponse(Response.Status.OK , "video/mp4" , null ,  -1)
            response.addHeader("Accept-Ranges", "bytes")
            response.addHeader("Content-Length", length)
            return response
        }

        val data = connectResponse.body ?: return null
        val contentLength = data.contentLength()
        val remoteStream = BufferedInputStream(data.byteStream())

        Log.e("--->", "getProxyVideoStream: range = $rangeHeader")
        val response = if(rangeHeader.isNullOrEmpty()){
            newFixedLengthResponse(Response.Status.OK, "video/mp4" , remoteStream , contentLength)
        }else{
            val range = rangeHeader.replace("bytes=", "").split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            val start = range[0].toLong()
            val end = if (range.size > 1) range[1].toLong() else contentLength - 1
            val responseLength = end - start + 1
            remoteStream.skip(start)
            val response = newFixedLengthResponse(Response.Status.PARTIAL_CONTENT, "video/mp4" , remoteStream , responseLength)
            response.addHeader("Content-Range", "bytes $start-$end/${contentLength}")
            response
        }

        //samsung支持快进快退
        //Streaming: 按需加载内容并流式传输。
        //Interactive: 支持范围请求（Range）。
        //Background: 直接传输完整内容。
        response.addHeader("Accept-Ranges", "bytes")
        response.addHeader("Connection", "keep-alive")
        response.addHeader("Access-Control-Allow-Origin", "*")
        response.addHeader("Access-Control-Allow-Headers", "*")
        response.addHeader("TimeSeekRange.DLNA.ORG", "npt=0.00-")
        response.addHeader("TransferMode.DLNA.ORG", "Streaming")
        response.addHeader("RealTimeInfo.DLNA.ORG", "DLNA.ORG_TLAG=*")
        response.addHeader("Content-Disposition", "inline; filename=stream")
        response.addHeader("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS")
        response.addHeader("ContentFeatures.DLNA.ORG", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000")

        return response
    }

    override fun serve(session: IHTTPSession?): Response {
        if(currentStreamUrl.isNullOrEmpty() || session == null) return super.serve(session)
        //Youtube视频中转
        if(session.uri.contains("proxyVideo")){
            return getProxyVideoStream(session) ?: super.serve(session)

        }
        return super.serve(session)
    }

    private fun showLog(log : String){
        Log.e("---->", "StreamVideoProxyServer: $log")
    }
}